package db;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class DatabaseManager {
    // Get a connection to the database
    private static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(DBConfigLoader.getUrl(), DBConfigLoader.getUser(), DBConfigLoader.getPassword());
    }

    public static void insertFlowResult(String apkName, String phase, long cnt,
                                        long leakCnt, long pathCnt,
                                        long dataCnt, long entityCnt,
                                        long conditionCnt, String tuples, String data, String entity, String permission) {
        String insertSQL = "INSERT INTO FlowResult " +
                "(apkName, phase, cnt,leakCnt,pathCnt, dataCnt, entityCnt, conditionCnt," +
                " Tuples, data, entity,permission, importedDatetime, modifiedDatetime) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)";

        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {

            pstmt.setString(1, apkName);
            pstmt.setString(2, phase);
            pstmt.setLong(3, cnt);
            pstmt.setLong(4, leakCnt);
            pstmt.setLong(5, pathCnt);
            pstmt.setLong(6, dataCnt);
            pstmt.setLong(7, entityCnt);
            pstmt.setLong(8, conditionCnt);
            pstmt.setString(9, tuples);
            pstmt.setString(10, data);
            pstmt.setString(11, entity);
            pstmt.setString(12, permission);

            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }


    public static void insertScanResult(String apkName, String phase, long visited,
                                        long coreMethodsNum, long tupleCnt,
                                        long dataCnt, long entityCnt,
                                        long permissionCnt, String tuples,
                                        String data, String entity, String permissions) {
        String insertSQL = "INSERT INTO ScanResult " +
                "(apkName, phase, visited,coreMethodsNum,tupleCnt, dataCnt, entityCnt, permissionCnt, Tuples, " +
                "data, entity,permissions, importedDatetime, modifiedDatetime) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)";

        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {

            pstmt.setString(1, apkName);
            pstmt.setString(2, phase);
            pstmt.setLong(3, visited);
            pstmt.setLong(4, coreMethodsNum);
            pstmt.setLong(5, tupleCnt);
            pstmt.setLong(6, dataCnt);
            pstmt.setLong(7, entityCnt);
            pstmt.setLong(8, permissionCnt);
            pstmt.setString(9, tuples);
            pstmt.setString(10, data);
            pstmt.setString(11, entity);
            pstmt.setString(12, permissions);

            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void insertDataFlowTime(String apkName, String phase, double duration) {
        String insertSQL = "INSERT INTO DataFlowTime (apkName, phase, duration, importedDatetime, modifiedDatetime) VALUES (?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)";

        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {

            pstmt.setString(1, apkName);
            pstmt.setString(2, phase);
            pstmt.setDouble(3, duration);

            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Deprecated
    public static void insertTuple(String apkName, String phase, long cnt, long dataCnt, long entityCnt,
                                   long conditionCnt, String tuples, String data, String entity) {
        String insertSQL = "INSERT INTO Tuples " +
                "(apkName, phase, cnt, dataCnt, entityCnt, conditionCnt, Tuples, data, entity, importedDatetime, modifiedDatetime) " +
                "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)";

        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {

            pstmt.setString(1, apkName);
            pstmt.setString(2, phase);
            pstmt.setLong(3, cnt);
            pstmt.setLong(4, dataCnt);
            pstmt.setLong(5, entityCnt);
            pstmt.setLong(6, conditionCnt);
            pstmt.setString(7, tuples);
            pstmt.setString(8, data);
            pstmt.setString(9, entity);

            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void insertSourceSinkFreq(String apkName, String signature, String type, int freq) {
        String insertSQL = "INSERT INTO SourceSinkFreq " +
                "(apkName,signature, type, freq, importedDatetime, modifiedDatetime) " +
                "VALUES (?,?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)";

        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(insertSQL)) {

            pstmt.setString(1, apkName);
            pstmt.setString(2, signature);
            pstmt.setString(3, type);
            pstmt.setInt(4, freq);

            pstmt.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}